package com.acmen.ump.core.handler;

import com.acmen.ump.core.dto.ApiResponse;
import com.acmen.ump.core.dto.ApiResponseErrorCode;
import com.acmen.ump.core.dto.ErrorEntity;
import com.acmen.ump.core.exception.BadRequestException;
import com.acmen.ump.core.exception.FileRequestException;
import com.acmen.ump.core.exception.JwtAuthenticationFailureException;
import com.acmen.ump.core.exception.RequestParamNotValidException;
import com.alibaba.fastjson.JSON;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.servlet.mvc.method.annotation.ResponseEntityExceptionHandler;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Objects;

/**
 * @author Acmen
 * @ClassName GlobalExceptionHandler.java
 * @Description 全局异常处理
 * @CreateTime 2019年08月23日 14:41:23
 */
@ControllerAdvice(annotations = RestController.class)
@SuppressWarnings({"unchecked"})
public class GlobalExceptionHandler extends ResponseEntityExceptionHandler {
    private static final Logger logger = LoggerFactory.getLogger(GlobalExceptionHandler.class);

    /**
     * 请求参数验证错误
     */
    @ExceptionHandler({RequestParamNotValidException.class})
    public ResponseEntity handleRequestParamNotValidException(
            RequestParamNotValidException ex) {

        logger.warn("参数验证错误： {}", ex.getBindingResult().getAllErrors());

        try {
            // 错误对象
            ApiResponse apiResponse = new ApiResponse();
            List<ErrorEntity> errorEntitys = new ArrayList<>();

            // 获取错误信息
            BindingResult errors = ex.getBindingResult();

            errors.getFieldErrors().forEach(error -> {
                ErrorEntity apiError = new ErrorEntity();
                apiError.setMessage(error.getCode());
                apiError.setField(error.getField());
                if (Objects.nonNull(error.getArguments())
                        && Objects.nonNull(error.getArguments()[0])) {
                    if (error.getArguments()[0] instanceof Map) {
                        apiError.setParams((Map) error.getArguments()[0]);
                    }
                }

                errorEntitys.add(apiError);
            });

            apiResponse.setErrors(errorEntitys);
            apiResponse.setCode(ApiResponseErrorCode.CODE_101.getCode());
            apiResponse.setMessage(ApiResponseErrorCode.CODE_101.getMessage());

            return new ResponseEntity(apiResponse, HttpStatus.BAD_REQUEST);

        } catch (Exception e) {

            logger.error("GlobalHandle构建response发生错误：", ex);

            // 错误对象
            ApiResponse apiResponse = new ApiResponse(ApiResponseErrorCode.CODE_999);

            return new ResponseEntity(apiResponse, HttpStatus.BAD_REQUEST);
        }
    }

    /**
     * 请求错误（非法/无效的请求）
     */
    @ExceptionHandler({BadRequestException.class})
    public ResponseEntity<ApiResponse<Void>> badRequestException(
            BadRequestException bre) {

        logger.warn("请求错误： {}", bre.getMessage());

        // 错误对象
        ApiResponse apiResponse = new ApiResponse();

        // 有详细错误抛出
        if (Objects.nonNull(bre.getMessage())) {
            List<ErrorEntity> errorEntitys = new ArrayList<>();
            ErrorEntity apiError = new ErrorEntity();
            apiError.setMessage(bre.getMessage());
            apiError.setParams(bre.getParams());
            errorEntitys.add(apiError);
            apiResponse.setErrors(errorEntitys);
        }

        apiResponse.setCode(ApiResponseErrorCode.CODE_101.getCode());
        apiResponse.setMessage(ApiResponseErrorCode.CODE_101.getMessage());

        return new ResponseEntity(apiResponse, HttpStatus.BAD_REQUEST);
    }

    /**
     * 文件上传异常处理
     */
    @ExceptionHandler(FileRequestException.class)
    @ResponseBody
    public String fileRequestException(FileRequestException fre) {

        logger.error("文件上传异常：{}", fre.getMessage());

        // 错误对象
        ApiResponse apiResponse = new ApiResponse();

        apiResponse.setCode(ApiResponseErrorCode.CODE_102.getCode());
        apiResponse.setMessage(fre.getMessage());

        return JSON.toJSONString(apiResponse);

    }

    /**
     * 未知异常处理
     */
    @ExceptionHandler(Exception.class)
    public ResponseEntity unknownException(Exception e) {

        logger.error("未知异常", e);

        // 错误对象
        ApiResponse apiResponse = new ApiResponse(ApiResponseErrorCode.CODE_999);

        return new ResponseEntity(apiResponse,
                HttpStatus.INTERNAL_SERVER_ERROR);

    }
    /**
     * JWT认证失败
     */
    @ExceptionHandler(JwtAuthenticationFailureException.class)
    public ResponseEntity jwtAuthenticationFailureException(Exception e) {

        logger.error("JWT认证失败");

        // 错误对象
        ApiResponse apiResponse = new ApiResponse(ApiResponseErrorCode.CODE_403);

        return new ResponseEntity(apiResponse,
                HttpStatus.UNAUTHORIZED);

    }

//    /**
//     * 请求被拒绝
//     */
//    @ExceptionHandler(Exception.class)
//    public ResponseEntity rejectRequestException(Exception e) {
//
//        logger.error("请求被拒绝", e);
//
//        // 错误对象
//        ApiResponse apiResponse = new ApiResponse(ApiResponseErrorCode.CODE_401);
//
//
//        return new ResponseEntity(apiResponse,
//                HttpStatus.FORBIDDEN);
//
//    }
//
//    /**
//     * Http认证失败
//     * @param e
//     * @return
//     */
//    public ResponseEntity httpAuthenticationFailureException(Exception e){
//        logger.error("HTTP认证失败", e);
//        // 错误对象
//        ApiResponse apiResponse = new ApiResponse(ApiResponseErrorCode.CODE_403);
//
//        return new ResponseEntity(apiResponse,HttpStatus.UNAUTHORIZED);
//
//    }
}
